﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using DotNetX;
using RPGX.ServerAdmin.Server;
using RPGX.Data;

namespace RPGX.ServerAdmin
{
    public partial class Main : Form
    {
        #region Properties

        public Server.Server Server
        {
            get { return _server; }
        }
        private Server.Server _server = new Server.Server();

        public List<int> NumberOfConnectedClients
        {
            get { return _numberOfConnectedClients; }
            set { _numberOfConnectedClients = value; }
        }
        private List<int> _numberOfConnectedClients = new List<int>();

        #endregion

        #region Public Methods

        public Main()
        {
            this.InitializeComponent();
        }

        #endregion

        #region Private Methods

        private void Main_Load(object sender, EventArgs e)
        {
            this.Server.Init();

            this.SetupServerStatus();
        }

        private void SetupServerStatus()
        {
            this.labelServerStatus.Text = this.Server.Status.GetDescription();

            if (this.Server.Status == ServerStatus.Started)
            {
                this.buttonRestartServer.Enabled = true;
                this.buttonStopServer.Enabled = true;
                this.buttonPauseServer.Enabled = true;
                this.buttonStartServer.Enabled = false;
            }
            else if (this.Server.Status == ServerStatus.Stopped)
            {
                this.buttonRestartServer.Enabled = false;
                this.buttonStopServer.Enabled = false;
                this.buttonPauseServer.Enabled = false;
                this.buttonStartServer.Enabled = true;
            }
            else if (this.Server.Status == ServerStatus.Paused)
            {
                this.buttonRestartServer.Enabled = false;
                this.buttonStopServer.Enabled = false;
                this.buttonPauseServer.Enabled = true;
                this.buttonStartServer.Enabled = false;

                this.buttonPauseServer.Text = "Resume";
            }
            else if (this.Server.Status == ServerStatus.Restarting ||
                     this.Server.Status == ServerStatus.Starting ||
                     this.Server.Status == ServerStatus.Stopping ||
                     this.Server.Status == ServerStatus.Pausing ||
                     this.Server.Status == ServerStatus.Resuming)
            {
                this.buttonRestartServer.Enabled = false;
                this.buttonStopServer.Enabled = false;
                this.buttonPauseServer.Enabled = false;
                this.buttonStartServer.Enabled = false;

                this.buttonPauseServer.Text = "Pause";
            }
        }

        private void buttonStartServer_Click(object sender, EventArgs e)
        {
            this.Server.Start();
            this.SetupServerStatus();

            this.StartServerStatusCheck();
        }

        private void buttonRestartServer_Click(object sender, EventArgs e)
        {
            this.Server.Restart();
            this.SetupServerStatus();

            this.StartServerStatusCheck();
        }

        private void buttonStopServer_Click(object sender, EventArgs e)
        {
            this.Server.Stop();
            this.SetupServerStatus();

            this.StartServerStatusCheck();
        }

        private void buttonPauseServer_Click(object sender, EventArgs e)
        {
            this.Server.Pause();
            this.SetupServerStatus();

            this.StartServerStatusCheck();
        }

        private void StartServerStatusCheck()
        {
            this.timerServerStatus.Tick += new EventHandler(timerServerStatus_Tick);
            this.timerServerStatus.Interval = 1000;

            this.timerServerStatus.Start();
        }

        private void timerServerStatus_Tick(object sender, EventArgs e)
        {
            if (this.Server.Status == ServerStatus.Stopped ||
                this.Server.Status == ServerStatus.Paused)
            {
                this.timerServerStatus.Stop();
            }

            this.SetupServerStatus();

            this.SetServerHealth();
        }

        private void SetServerHealth()
        {
            try
            {
                RPGXServerEntities context = new RPGXServerEntities();

                var latest = context.ServerHealths.OrderByDescending(h => h.DateCreated).FirstOrDefault();
                if (latest == null)
                    return;

                int currentNumberOfClients = context.Players.Where(p => p.IsActive == true).Count();
                this.NumberOfConnectedClients.Add(currentNumberOfClients);

                if (this.NumberOfConnectedClients.Count > 100)
                    this.NumberOfConnectedClients.Remove(100);

                var averageCPUUsage = context.ServerHealths.Take(100).Where(s => s.CPUUsage < 100).Average(s => (decimal?)s.CPUUsage); // remove any excentric cpu values
                if (averageCPUUsage == null)
                    averageCPUUsage = 0; // why this would ever be null, I have no idea...

                var averageMemoryUsage = context.ServerHealths.Take(100).Average(s => s.TotalMemory);
                var averageThreads = context.ServerHealths.Take(100).Average(s => s.NumberOfThreads);
                var averageClients = this.NumberOfConnectedClients.Average();

                this.labelCurrentCPUUsage.Text = String.Format("{0}%", latest.CPUUsage);
                this.labelCurrentMemoryUsage.Text = String.Format("{0} MB", ((latest.TotalMemory / 1024.0f) / 1024.0f)); // use the linq method average
                this.labelCurrentNumberOfThreads.Text = String.Format("{0}", latest.NumberOfThreads);
                this.labelCurrentNumberOfClients.Text = String.Format("{0}", currentNumberOfClients);

                this.labelAverageCPUUsage.Text = String.Format("{0}%", averageCPUUsage);
                this.labelAverageMemoryUsage.Text = String.Format("{0} MB", ((averageMemoryUsage / 1024.0f) / 1024.0f));
                this.labelAverageNumberOfThreads.Text = String.Format("{0}", averageThreads);
                this.labelAverageNumberOfClients.Text = String.Format("{0}", averageClients);

                this.labelUpDate.Text = String.Format("{0:dd/MM/yyyy hh:mm:ss}", this.Server.StartTime);
                this.labelUpTime.Text = String.Format("{0}", this.Server.UpTime);
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }

        #endregion
    }
}
